expo(react native)のreact-nativationのbottom tabで任意のsvgアイコンを表示する方法を解説します。 svgは.svgファイルから読み込んで表示させます。こうしておくと、figmaなどからDLしたものをそのまま読み込ませれるから便利です。
また、assetsは@assets
でインポートできるようエイリアスを設定します。
1. ライブラリのインストール
まずはreact-navigationのbottom-tabsとsvg関係のライブラリをインストールします。
関連記事
https://reactnavigation.org/docs/bottom-tab-navigator https://docs.expo.dev/versions/latest/sdk/svg/ https://blog.logrocket.com/how-to-use-svgs-react-native-tutorial-with-examples/
インストールコマンド
$ yarn add @react-navigation/bottom-tabs
$ npx expo install react-native-svg
$ yarn add -D react-native-svg-transformer
$ yarn add -D babel-plugin-inline-import
ビルド時にsvgファイルを読み込んだり、importできるようにするため、transformerなどもここで一緒にインストールします。
2. 設定
metro.config.js
metro.config.jsを編集します、ない人はプロジェクト直下に作成して下さい。
const { getDefaultConfig } = require('metro-config')
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts },
} = await getDefaultConfig()
return {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
},
}
})()
babel.config.js
エイリアスの設定や、svgファイル読み込みの設定を行います。
module.exports = function (api) {
api.cache(true)
return {
presets: ['babel-preset-expo'],
plugins: [
[
'module-resolver',
{
alias: {
'@': './src',
'@assets': './assets',
},
extensions: ['.js', '.jsx', '.ts', '.tsx', '.svg'],
},
],
[
'babel-plugin-inline-import',
{
extensions: ['.svg'],
},
],
],
}
}
3. アイコンの定義
私の場合は、アイコン表示用のatom(コンポーネント)を追加して、アイコンの定義、表示を一元管理するようにしました。
IconAtomType.ts
export const IconType = {
Home: 'home',
Favorite: 'favorite',
} as const
export type IconType = typeof IconType[keyof typeof IconType]
なんかenumの書き方は最近嫌われているみたいで、あんまり好きじゃないのですけどこっちの定義の仕方にしました。 https://weseek.co.jp/tech/1609/
Icon.tsx
requireで@assetsでsvgの読み込みをします。
import React from 'react'
import { IconType } from '@/types/atoms/IconAtomType'
const Home = require('@assets/svg/home.svg').default
const Favorite = require('@assets/svg/favorite.svg').default
interface IconProps {
type: IconType
}
/**
* アイコン表示
*/
const Icon: React.FC<IconProps> = ({ type }) => {
switch (type) {
case IconType.Home:
return <Home />
case IconType.Favorite:
return <Favorite />
}
}
export default Icon
4. bottom tabの定義
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import FavoritePage from '@/pages/FavoritePage'
import HomePage from '@/pages/HomePage'
import Icon from '@/components/atoms/Icon'
import { IconType } from '@/types/atoms/IconAtomType'
const Tab = createBottomTabNavigator()
const RouterStack = () => {
return (
<Tab.Navigator
initialRouteName={'home'}
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
switch (route.name) {
case 'home':
return <Icon type={IconType.Home} />
case 'favorite':
return <Icon type={IconType.Favorite} />
}
return undefined
},
})}
>
<Tab.Screen name={'home'} component={HomePage} />
<Tab.Screen name={'favorite'} component={FavoritePage} />
</Tab.Navigator>
)
}
export default RouterStack
ボトムタブに任意のsvgアイコンを表示できました。